// 知识点1：当类之间存在继承关系时，派生类的作用域嵌套在其基类的作用域之内，如果一个名字在派生类作用域中找不到定义，则编译器会继续在外层基类中寻找

// 知识点2：派生类可以重用定义在其直接基类或者间接基类中的名字，此时定义在内层作用域的名字将隐藏外层作用于中的名字，但是我们可以使用作用域运算符来访问使用隐藏的基类成员

// 知识点3：除了覆盖虚函数，派生类最好不要重用其他基类中的名字

// 知识点4：函数的调用及解析过程：

// 1：确定其静态类型，必然是一个类类型

// 2：在其静态类型的类中查找该成员，找不到，则向外层的基类移动，再没有，编译器报错

// 3：找到了该成员，进行常规的类型检查，编译器再根据其是否是虚函数产生不同的代码

// 若是虚函数且为引用或者指针类型的调用，则需要进行动态绑定，编译器产生的运行代码在运行时将决定到底运行该虚函数的哪个版本，依据其动态类型

// 若不是虚函数或是没有指针引用调用，则产生常规调用

// 知识点5：内层作用域中的函数不会重载外层作用域中的函数，所以派生类成员若有名字相同，即使其形参列表不一致，基类成员也会被隐藏掉—名字查找优先于类型检查

#include <algorithm>
#include <iostream>
#include <vector>

// #include "Quote.h"
// #include "Disc_quote.h"
// #include "Base.h"
using namespace std;

struct base {
  void Foo14();
};

struct Derived : base {
  void Foo14(int); //会隐藏掉基类中的相应成员
};

int main(int argc, char **argv) {
  Derived d;
  base b;
  b.Foo14();
  d.Foo14(10);
  // d.Foo14(); //错误
  d.base::Foo14();
  return 0;
}
// 知识点6：由知识点5，基类和派生类的虚函数参数列表必须相同，并且可以通过基类的作用域运算符调用基类的虚函数，若派生类的与基类虚函同名的成员参数列表与虚函数不同，那么派生类中的成员并没有覆盖基类的相应虚函数，因为形参列表不一致，派生类将拥有两个同名成员。

// 由知识点6：若要覆盖，则需要形参列表一致

int fcn();
// 只有虚函数调用将存在，fcn(int)类型的调用都将错误